package tech.yozo.bamboo.ui.capture;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.FocusMeteringResult;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.MeteringPointFactory;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;

import com.google.common.util.concurrent.ListenableFuture;

import java.io.File;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

import tech.yozo.bamboo.MainActivity;
import tech.yozo.bamboo.R;
import tech.yozo.bamboo.databinding.FragmentCaptureBinding;
import tech.yozo.bamboo.ui.reading.ReadingViewModel;
import tech.yozo.bamboo.utils.MimeType;

public class CaptureFragment extends Fragment {
    private FragmentCaptureBinding binding;

    private CameraControl cameraControl;
    private ImageCapture imageCapture;

    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentCaptureBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        Context context = requireContext();
        startCamera(context);
        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    /**
     * 启动相机
     * @param context 上下文
     */
    @SuppressLint("ClickableViewAccessibility")
    private void startCamera(Context context) {
        Executor mainExecutor = ContextCompat.getMainExecutor(context);

        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(context);
        cameraProviderFuture.addListener(() -> {
            PreviewView previewView = binding.previewView;
            // 拍照
            imageCapture = new ImageCapture.Builder().build();
            // 预览
            Preview preview = new Preview.Builder().build();
            preview.setSurfaceProvider(previewView.getSurfaceProvider());
            previewView.setOnTouchListener((v, event) -> {
                // 拍照
                takePicture(context);

                // 对焦并拍照
//            focus(event);

                return true;
            });

            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                cameraProvider.unbindAll();
                Camera camera = cameraProvider.bindToLifecycle(getViewLifecycleOwner(), CameraSelector.DEFAULT_BACK_CAMERA, preview, imageCapture);
                cameraControl = camera.getCameraControl();
            } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, mainExecutor);
    }

    /**
     * 对焦并拍照
     * @param event 点击事件
     */
    @Deprecated
    private void focus(MotionEvent event) {
        Context context = requireContext();
        Executor mainExecutor = ContextCompat.getMainExecutor(context);

        MeteringPointFactory meteringPointFactory = binding.previewView.getMeteringPointFactory();
        FocusMeteringAction action = new FocusMeteringAction.Builder(meteringPointFactory.createPoint(event.getX(), event.getY()), FocusMeteringAction.FLAG_AF).setAutoCancelDuration(3, TimeUnit.SECONDS).build();
        ListenableFuture<FocusMeteringResult> future = cameraControl.startFocusAndMetering(action);
        future.addListener(() -> {
            try {
                FocusMeteringResult result = future.get();
                if (result.isFocusSuccessful()) {
                    // 拍照
                    takePicture(context);
                }
            } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, mainExecutor);
    }

    /**
     * 拍照并识别
     */
    private void takePicture(Context context) {
        Executor mainExecutor = ContextCompat.getMainExecutor(context);

        imageCapture.takePicture(mainExecutor, new ImageCapture.OnImageCapturedCallback() {
            @Override
            public void onCaptureSuccess(@NonNull ImageProxy imageProxy) {
                // OCR识别
                ReadingViewModel model =  new ViewModelProvider(requireActivity()).get(ReadingViewModel.class);
                model.doOCR(imageProxy);
                imageProxy.close();

                // 先跳转到识别页面
                Bundle bundle = new Bundle();
                bundle.putString("type", MimeType.MIME_TYPE_PNG);
                NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment_content_main);
                navController.navigate(R.id.nav_reading, bundle);
            }
        });
    }

    @Deprecated
    private void takePicture2(Context context) {
        Executor mainExecutor = ContextCompat.getMainExecutor(context);

        ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(new File(context.getCacheDir(), "temp.jpg")).build();
        imageCapture.takePicture(options, mainExecutor, new ImageCapture.OnImageSavedCallback() {
            @Override
            public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                Intent intent = new Intent(context, MainActivity.class);
                intent.putExtra("image_uri", Objects.requireNonNull(outputFileResults.getSavedUri()).toString());
                startActivity(intent);
            }

            @Override
            public void onError(@NonNull ImageCaptureException exception) {
                Log.e("OCR", exception.toString());
            }
        });
    }
}